package cn.tedu._07springaop.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 切面类
 * Aspect注解:
 *   1.标识当前类为切面类;
 *   2.当调用目标方法时,框架先检查有没有切面类,再检查有没有对应的切面方法;
 */

@Aspect
@Component
public class LogAspect {

    /**
     * Pointcut注解: 定义切入点表达式的方法;
     */
    @Pointcut("execution(public int cn.tedu._07springaop.aop.CalculatorImpl.*(..))")
    public void doTime(){}


//    /**
//     * 1.Before注解: 前置通知,调用目标方法[add() sub() mul() div()]之前需要执行的方法;
//     * 2.参数为:切入点表达式,指定哪些方法需要被拦截植入扩展业务逻辑;
//     */
//    @Before("doTime()")
//    public void beforeMethod(JoinPoint joinPoint){
//        /*
//            JoinPoint是连接点对象,即拦截到的目标方法的对象;
//            1.获取方法名称: joinPoint.getSignature().getName();
//            2.获取参数列表: joinPoint.getArgs();
//         */
//        String name = joinPoint.getSignature().getName();
//        String args = Arrays.toString(joinPoint.getArgs());
//
//        System.out.println(name + "方法开始,参数为:" + args);
//    }
//
//    /**
//     * After:
//     *   1.后置通知,目标方法执行结束[正常结束 || 异常结束]后执行此方法;
//     *   2.后置通知没有权限获取目标方法的返回值;
//     */
//    @After("doTime()")
//    public void afterMethod(JoinPoint joinPoint){
//        String name = joinPoint.getSignature().getName();
//        System.out.println(name + "方法执行彻底结束");
//    }
//
//    /**
//     * AfterReturning
//     *   1.返回通知:目标方法正常结束后执行,异常结束则不会执行;
//     *   2.返回通知有权限获取目标方法的返回值;
//     */
//    @AfterReturning(value = "doTime()", returning = "result")
//    public void afterReturningMethod(JoinPoint joinPoint, Object result){
//        String name = joinPoint.getSignature().getName();
//        System.out.println(name + "方法执行结束,结果为:" + result);
//    }
//
//    /**
//     * AfterThrowing
//     *   1.异常通知: 目标方法抛出异常时执行;
//     *   2.异常通知有权限拿到目标方法抛出的异常对象;
//     */
//    @AfterThrowing(value = "doTime()", throwing = "ex")
//    public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
//        String name = joinPoint.getSignature().getName();
//        String data = ex.getMessage();
//        System.out.println(name + "方法抛出异常,提示消息为:" + data);
//    }

    /**
     * Around
     *   1.环绕通知: 等价于 前置通知+后置通知+返回通知+异常通知;
     *   2.环绕通知: 有权限执行目标方法!!! 通常使用 try ... catch ... finally 包裹;
     */
    @Around("doTime()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        try {
            /*
                1.前置通知;
                2.执行目标方法;
                3.返回通知;
             */
            System.out.println("[环绕通知]:前置通知");
            result = joinPoint.proceed();
            System.out.println("[环绕通知]:返回通知");
        } catch (Throwable e){
            //4.异常通知
            System.out.println("[环绕通知]:异常通知");
        } finally {
            //5.后置通知
            System.out.println("[环绕通知]:后置通知");
        }

        return result;
    }
}











